package org.longteng.mobileluck.algorithm.dao.impl;

import com.univocity.parsers.common.processor.BeanListProcessor;
import com.univocity.parsers.csv.CsvParser;
import com.univocity.parsers.csv.CsvParserSettings;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.util.List;


/**
 * 机号码运势说明表数据读入csv实现
 * <br>带有泛型的抽象类:abstract class 类名<无意义的占位符>{
 * @author hymn.com
 */
@Slf4j
public abstract class ParserCsvBaseDao<T>  {

    /**
     * 读取CSV数据表
     * @return
     */
    protected List<T> readTableCsv(String relativeCsvFile) {
        List<T> dataList = null;
        BeanListProcessor<T> rowProcessor = new BeanListProcessor<T>(this.getTClass());
        CsvParserSettings parserSettings = new CsvParserSettings();
        parserSettings.setProcessor(rowProcessor);
        parserSettings.setHeaderExtractionEnabled(true);

        CsvParser parser = new CsvParser(parserSettings);
        try(Reader csvReader = this.getCsvReader(relativeCsvFile)) {
            parser.parse(csvReader);

            // BeanListProcessor从输入中提取出一个对象列表
            dataList = rowProcessor.getBeans();
            if(log.isDebugEnabled()) {
                log.debug("读取CSV数据表成功。，数据行数：{}; {}", dataList==null?0:dataList.size(), relativeCsvFile);
            }
        }catch (IOException e) {
            log.error("读取CSV数据表错误。", e);
        }
        return dataList;
    }

    /**
     * 从资源中读入csv文件
     * @param relativePath
     * @return
     */
    protected Reader getCsvReader(String relativePath) {
        return new InputStreamReader(this.getClass().getResourceAsStream(relativePath), StandardCharsets.UTF_8);
    }

    /**
     * 获取泛型T的类型 T.class
     * <br>Class<T> tClass = (Class<T>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
     * <br>可能会有错误：java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
     * <br>子类直接实现返回真实类class
     * @return
     */
    public abstract Class getTClass();
}
